package user.source;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import message.MissileDeadMsg;
import message.MissileNewMsg;
import message.Msg;
import message.TankDeadMsg;
import message.TankMoveMsg;
import message.TankNewMsg;
import server.TankServer;

/**
 * 
 * @author
 *
 */
public class NetClient {
	static final int IN = 2;
	/**
	 * 用一个TankClient的引用来将id号传入到坦克中
	 */
	TankClient tc;
	private int udpPort;

	/**
	 * server的IP地址
	 */
	String ip;

	public int getUdpPort() {
		return udpPort;
	}

	public void setUdpPort(int udpPort) {
		this.udpPort = udpPort;
	}

	DatagramSocket ds = null;

	public NetClient(TankClient tc) {
		this.tc = tc;
	}

	/**
	 * 用来进行客户端与服务器连接的方法（此时已经处理好TCP的相关事宜
	 * 
	 * @param ip
	 * @param port
	 */
	public void connect(String ip, int port) {

		this.ip = ip;

		try {
			// 连接UDPport
			ds = new DatagramSocket(udpPort);
		} catch (SocketException e) {
			e.printStackTrace();
		}

		Socket socket = null;
		try {
			socket = new Socket(ip, port);
			DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
			dos.writeInt(udpPort);
			// 从服务器接受一个代表自己的独一无二的ID
			DataInputStream dis = new DataInputStream(socket.getInputStream());
			int id = dis.readInt();
			// 服务器分配给我的坦克一个独一无二的ID号
			tc.myTank.id = id;
			System.out.println("Server have give me an id!");
			if (id % IN == 0) {
				tc.myTank.good = false;
			} else {
				tc.myTank.good = true;
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (socket != null) {
				try {
					socket.close();
					socket = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		// 产生一条坦克生成的消息（UDP），告诉服务器我已连接
		TankNewMsg msg = new TankNewMsg(tc.myTank);
		// 发送UDP包到服务器
		send(msg);

		// 当TCP连接成功时，启动下方的UDP接收线程
		Thread t = new UdpReceiveThread();
		t.start();

	}

	/**
	 * 将客户端的信息发出去的方法
	 * 
	 * @param msg
	 */
	public void send(Msg msg) {
		// 将消息从ds端口发送出去
		msg.send(ds, ip, TankServer.UDP_PORT);
	}

	/**
	 * 客户端接收数据包的线程
	 * 
	 * @author
	 *
	 */
	private class UdpReceiveThread extends Thread {
		byte[] buffer = new byte[1024];

		@Override
		public void run() {

			// 只要端口建立起来，就可以传输客户端的数据了
			while (ds != null) {
				// 我们有了一个1024字节的包
				DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
				try {
					// 一旦拿到了一包数据
					ds.receive(dp);
					// 对数据包进行解析
					parse(dp);
					System.out.println("a packet receive from Server!");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		// 用来解析UDP数据包的方法
		private void parse(DatagramPacket dp) {
			ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, dp.getLength());
			DataInputStream dis = new DataInputStream(bais);
			int msgType = 0;

			try {
				msgType = dis.readInt();
			} catch (IOException e) {
				e.printStackTrace();
			}

			Msg msg = null;
			switch (msgType) {
			case Msg.TANK_NEW_MSG:
				msg = new TankNewMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.TANK_MOVE_MSG:
				msg = new TankMoveMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.MISSILE_NEW_MSG:
				msg = new MissileNewMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.TANK_DEAD_MSG:
				msg = new TankDeadMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.MISSILE_DEAD_MSG:
				msg = new MissileDeadMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			default:
			}

		}
	}

}
